from machine import Timer
import gc
from utime import sleep, time
from config import Config
from utils import WifiHandler
from utils import Utilities
from drivers.led import Led

forever_loop = True
dht11 = None
ds18b20 = None
ap_server = None
dns_server = None
mqtt_client = None
button = None
led = None
mqtt_ping_timer = Timer(0)
mqtt_ping_counter = 0
mqtt_ping_keepalive = 0


def get_temp_and_humi():
	global dht11

	print("Current temperature: {temp}(°C)\nCurrent humidity: {humi}(%)".format(**dht11.temperature_and_humidity()))

def get_temperature():
	global ds18b20

	print("Current temperature: {}(°C)".format(ds18b20.temperature()))

def main():
	if Config.HARDWARE_VERSION == Config.VERSION_1:
		get_temp_and_humi()
	elif Config.HARDWARE_VERSION == Config.VERSION_2:
		get_temperature()

def mqtt_ping_cb(timer):
	import urandom

	global mqtt_client, mqtt_ping_counter, mqtt_ping_keepalive
	
	mqtt_ping_counter += 1

	if mqtt_ping_counter >= mqtt_ping_keepalive:
		print("ping", urandom.randint(1, 65535))

		try:
			mqtt_client.subscribe(b'walkline/ping')
			# mqtt_client.ping()
			mqtt_ping_counter = 0
		except OSError as ose:
			print("err time:", time())
			print(str(ose))

			if str(ose) in ("[Errno 104] ECONNRESET", "-1"):
				try:
					mqtt_client.disconnect()
				except OSError:
					pass
				finally:
					mqtt_client.connect()

	gc.collect()

def connect_to_emqx_server():
	global mqtt_client, mqtt_ping_timer, mqtt_ping_keepalive

	try:
		from settings import Settings
	except ImportError:
		Utilities.enter_smart_config_mode()

	from umqtt.simple import MQTTClient

	mqtt_client = MQTTClient(
		Settings.MQTT_DEVICE_NAME,
		Settings.MQTT_HOST,
		Settings.MQTT_PORT,
		Settings.MQTT_DEVICE_NUMBER,
		Settings.MQTT_DEVICE_AUTHORIZE,
		Settings.MQTT_KEEPALIVE,
	)

	# mqtt_client.set_last_will(b'walkline/last_will', b'offline')
	mqtt_client.set_callback(sub_cb)
	mqtt_client.connect()
	
	mqtt_ping_keepalive = Settings.MQTT_KEEPALIVE
	mqtt_ping_timer.init(mode=Timer.PERIODIC, period=1000, callback=mqtt_ping_cb)

	print("emqx forever loop")
	print("now:", time())
	# mqtt_client.subscribe(b'walkline/walkline_weather_station_v1')
	# mqtt_client.wait_msg()

def sub_cb(topic, msg):
	print("topic:", topic)
	print("msg:", msg)

def button_press_cb(times):
	def reboot_cb():
		Utilities.enter_smart_config_mode()

	led = Led(2, reboot_cb)
	led.blink_reboot()

	print("button pressed over {} ms".format(times))

def button_click_cb():
	import json, urandom
	from settings import Settings

	global mqtt_client

	data = json.dumps({
		'key': Settings.MQTT_DATA_POINT[0],
		'vlue': urandom.randint(5, 40)
	})

	# 发送一个随机数据到 MQTT 平台
	mqtt_client.publish("{}/data".format(Settings.MQTT_USERNAME), data)

	print("button clicked")

def setup_hardware():
	"""
	根据硬件版本初始化硬件
	"""
	from drivers.button import Button
	from drivers.ds18b20 import DS18B20
	from drivers.dht11 import DHT11

	global dht11, ds18b20, button

	if Config.HARDWARE_VERSION == Config.VERSION_1:
		print("Current version: Version_1")

		dht11 = DHT11(Config.DHT11_DATALINE)
	elif Config.HARDWARE_VERSION == Config.VERSION_2:
		print("Current version: Version_2")

		ds18b20 = DS18B20(Config.DS18B20_DATALINE)

	button = Button(
		pin=Config.BUTTON,
		click_cb=button_click_cb,
		press_cb=button_press_cb,
		timeout=5000
	)


if __name__ == "__main__":
	try:
		if not Utilities.is_mode_file_exist():
			# 进入用户配网模式
			from service import WebServer, DNSServer

			led = Led(2)
			led.blink_fast(repeat=5)

			WifiHandler.set_ap_mode()
			WifiHandler.set_sta_status(False)
			sleep(1)

			ap_server = WebServer(root_path=Config.AP_ROOTPATH)
			ap_server.bind_address(Config.AP_HOST, Config.AP_PORT)
			ap_server.start()

			dns_server = DNSServer(Config.DNS_PORTAL)
			dns_server.start()

			while ap_server.is_running():
				sleep(0.5)
		else:
			# 进入工作模式
			led = Led(2)
			led.blink_medium(repeat=0)

			WifiHandler.set_ap_status(False)
			sleep(1)

			setup_hardware()

			if WifiHandler.STATION_CONNECTED == Utilities.connect_to_internet():
				led.stop()
				main()
				connect_to_emqx_server()

				while forever_loop:
					sleep(0.5)
			else:
				# 10秒后无法连接指定的 wifi 则进入配网模式
				Utilities.enter_smart_config_mode()
	except KeyboardInterrupt:
		forever_loop = False

		try:
			mqtt_client.disconnect()
		except:
			pass

		print("\nPRESS CTRL+D TO RESET DEVICE")

		if ap_server is not None: ap_server.stop()
		if dns_server is not None: dns_server.stop()
		if button is not None: button.deinit()
		if led is not None: led.deinit()
		mqtt_ping_timer.deinit()
